home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 15 / CU Amiga Magazine's Super CD-ROM 15 (1997)(EMAP Images)(GB)[!][issue 1997-10].iso / CUCD / Graphics / Ghostscript / source / gs_ttf.ps < prev    next >
Text File  |  1996-12-10  |  14KB  |  447 lines

  1. %    Copyright (C) 1996 Aladdin Enterprises.  All rights reserved.
  2. % This file is part of Aladdin Ghostscript.
  3. % Aladdin Ghostscript is distributed with NO WARRANTY OF ANY KIND.  No author
  4. % or distributor accepts any responsibility for the consequences of using it,
  5. % or for whether it serves any particular purpose or works at all, unless he
  6. % or she says so in writing.  Refer to the Aladdin Ghostscript Free Public
  7. % License (the "License") for full details.
  8. % Every copy of Aladdin Ghostscript must include a copy of the License,
  9. % normally in a plain ASCII text file named PUBLIC.  The License grants you
  10. % the right to copy, modify and redistribute Aladdin Ghostscript, but only
  11. % under certain conditions described in the License.  Among other things, the
  12. % License requires that the copyright notice and this notice be preserved on
  13. % all copies.
  14.  
  15. % Support code for direct use of TrueType fonts.
  16. % (Not needed for Type 42 fonts.)
  17.  
  18. % ---------------- Font loading machinery ---------------- %
  19.  
  20. % Augment the FONTPATH machinery so it recognizes TrueType fonts.
  21.  
  22. /.scanfontheaders where        % only defined if DISKFONTS is recognized
  23.  { pop
  24.    /.scanfontheaders [ .scanfontheaders aload pop (\000\001\000\000*) ] def
  25.  }
  26. if
  27. /.findnonttfontvalue /.findfontvalue load def
  28. /.findfontvalue        % <file> <key> .findfontvalue <value> true
  29.             % <file> <key> .findfontvalue false
  30.             % Closes the file in either case.
  31.  { 1 index read pop 2 index 1 index unread 0 eq
  32.     {        % If this is a font at all, it's a TrueType font.
  33.       dup /FontType eq
  34.        { pop closefile 42 true }
  35.        { dup /FontName eq
  36.       { pop .findttfontname }
  37.       { pop closefile false }
  38.      ifelse
  39.        }
  40.       ifelse
  41.     }
  42.     {        % Not a TrueType font.
  43.       .findnonttfontvalue
  44.     }
  45.    ifelse
  46.  } bind def
  47. /.findttfontname    % <file> .findttfontname <fname> true
  48.             % <file> .findttfontname false
  49.             % Closes the file in either case.
  50.  { .loadttfonttables
  51.    (name) findtableentry
  52.     { dup 8 getu32 f exch setfileposition
  53.       12 getu32 string f exch readstring pop
  54.       6 findname
  55.     }
  56.     { false
  57.     }
  58.    ifelse
  59.    f closefile end end
  60.  } bind def
  61.  
  62. % Load a font file that might be a TrueType font.
  63.  
  64. /.loadnonttfontfile /.loadfontfile load def
  65. /.loadfontfile        % <file> .loadfontfile -
  66.  { dup read pop 2 copy unread 0 eq
  67.     {        % If this is a font at all, it's a TrueType font.
  68.       .loadttfont dup /FontName get exch definefont pop
  69.     }
  70.     {        % Not a TrueType font.
  71.       .loadnonttfontfile
  72.     }
  73.    ifelse
  74.  } bind def
  75.  
  76. % ---------------- Automatic Type 42 generation ---------------- %
  77.  
  78. % Load a TrueType font from a file as a Type 42 PostScript font.
  79. % The thing that makes this really messy is the handling of encodings.
  80. % There are 3 interacting tables that affect the encoding:
  81. %    'cmap' provides multiple maps from character codes to glyph indices
  82. %    'glyf' maps glyph indices to outlines
  83. %    'post' maps glyph indices to glyph names (if present)
  84. % What we need to get out of this is:
  85. %    Encoding mapping character codes to glyph names
  86. %      (the composition of cmap and post)
  87. %    CharStrings mapping glyph names to glyph indices
  88. %      (the inverse of post)
  89. % If the post table is missing, we have to take a guess based on the cmap
  90. % table.
  91.  
  92. /.loadttfontdict mark
  93. /orgXUID 107 def    % Aladdin Enterprises organization XUID
  94. /maxstring 65500 def    % maximum length of a PostScript string
  95.  
  96. % Define the Macintosh standard mapping from characters to glyph indices.
  97. /MacRomanEncoding dup .findencoding def
  98. /MacGlyphEncoding mark
  99.     /.notdef /.null /CR
  100. MacRomanEncoding 32 95 getinterval aload pop
  101. MacRomanEncoding 128 45 getinterval aload pop
  102. % 143
  103.     /notequal /AE
  104.     /Oslash /infinity /plusinus /lessequal /greaterequal
  105.     /yen /mu1 /partialdiff /summation /product
  106.     /pi /integral /ordfeminine /ordmasculine /Ohm
  107.     /ae /oslash /questiondown /exclamdown /logicalnot
  108.     /radical /florin /approxequal /increment /guillemotleft
  109.     /guillemotright /ellipsis /nbspace
  110. MacRomanEncoding 203 12 getinterval aload pop
  111.     /lozenge
  112. MacRomanEncoding 216 24 getinterval aload pop
  113.     /applelogo
  114. MacRomanEncoding 241 7 getinterval aload pop
  115.     /overscore
  116. MacRomanEncoding 249 7 getinterval aload pop
  117. % 226
  118.     /Lslash /lslash /Scaron /scaron
  119.     /Zcaron /zcaron /brokenbar /Eth /eth
  120.     /Yacute /yacute /Thorn /thorn /minus
  121.     /multiply /onesuperior /twosuperior /threesuperior /onehalf
  122.     /onequarter /threequarters /franc /Gbreve /gbreve
  123.     /Idot /Scedilla /scedilla /Cacute /cacute
  124.     /Ccaron /ccaron /dmacron
  125. /packedarray where
  126.  { pop counttomark packedarray exch pop }
  127.  { ] readonly }
  128. ifelse def
  129.  
  130. % Procedures
  131. /getu16            % <string> <index> getu16 <integer>
  132.  { 2 copy get 8 bitshift 3 1 roll 1 add get add
  133.  } bind def
  134. /gets16            % <string> <index> gets16 <integer>
  135.  { getu16 16#8000 xor 16#8000 sub
  136.  } bind def
  137. /getu32            % <string> <index> getu32 <integer>
  138.  { 2 copy getu16 16 bitshift 3 1 roll 2 add getu16 add
  139.  } bind def
  140. /gets32            % <string> <index> gets32 <integer>
  141.  { getu32 dup 16#7fffffff gt { 4 { 16#40000000 sub } repeat } if
  142.  } bind def
  143. /getrange        % <offset> <length> getrange <string>
  144.             % Free variables: sfnts
  145.  { () sfnts
  146.     {        % Stack: offset length () sfnt
  147.       dup length 4 index gt { exch pop exit } if
  148.       4 -1 roll exch length sub 3 1 roll
  149.     }
  150.    forall 3 1 roll getinterval
  151.  } bind def
  152. /findtableentry        % <name4> findtableentry <tableentry> true
  153.             % <name4> findtableentry false
  154.             % Free variables: tables
  155.  { false 0 16 tables length 16 sub
  156.     {        % Stack: name4 false toffset
  157.       tables 1 index 4 getinterval 3 index eq
  158.        { tables exch 16 getinterval
  159.      exch pop exch true exit
  160.        }
  161.       if pop
  162.     }
  163.    for exch pop
  164.  } bind def
  165. /findtable        % <name4> findtable <table> true
  166.             % <name4> findtable false
  167.             % Free variables: tables
  168.  { findtableentry
  169.     { dup 8 getu32 exch 12 getu32 getrange true }
  170.     { false }
  171.    ifelse
  172.  } bind def
  173. /findname        % <nametable> <nameid> findname <string> true
  174.             % <nametable> <nameid> findname false
  175.  { false 3 1 roll 0 1 3 index 2 getu16 1 sub
  176.     {        % Stack: false table id index
  177.       12 mul 6 add 2 index exch 12 getinterval
  178.       dup 6 getu16 2 index eq
  179.        {    % We found the name we want.
  180.      exch pop
  181.         % Stack: false table record
  182.      dup 10 getu16 2 index 4 getu16 add
  183.      1 index 8 getu16 4 -1 roll 3 1 roll getinterval exch
  184.         % Stack: false string record
  185.         % Check for 8- vs. 16-bit characters.
  186.      is2byte { string2to1 } if true null 4 -1 roll exit
  187.        }
  188.       if pop
  189.     }
  190.    for pop pop
  191.  } bind def
  192. /is2byte        % <namerecord> is2byte <bool>
  193.  { dup 0 getu16
  194.     { { pop true }        % Apple Unicode
  195.       { pop false }        % Macintosh Script manager
  196.       { 1 getu16 1 eq }        % ISO
  197.       { 1 getu16 1 eq }        % Microsoft
  198.     }
  199.    exch get exec
  200.  } bind def
  201. /string2to1        % <string2> string2to1 <string>
  202.  { dup length 2 idiv string dup
  203.    0 1 3 index length 1 sub
  204.     { 3 index 1 index 2 mul 1 add get put dup }
  205.    for pop exch pop
  206.  } bind def
  207. /cmapformats mark
  208.         % Each procedure in this dictionary is called as follows:
  209.         %    -mark- encodingtable <<proc>> -mark- glyphindices...
  210.   0        % Apple standard 1-to-1 mapping.
  211.     { 6 256 getinterval { } forall
  212.     } bind
  213.   4        % Microsoft/Adobe segmented mapping.
  214.     { /etab exch def
  215.       /nseg2 etab 6 getu16 def
  216.       14 /endc etab 2 index nseg2 getinterval def
  217.         % The Apple TrueType documentation omits the 2-byte
  218.         % 'reserved pad' that follows the endCount vector!
  219.       2 add
  220.       nseg2 add /startc etab 2 index nseg2 getinterval def
  221.       nseg2 add /iddelta etab 2 index nseg2 getinterval def
  222.       nseg2 add /idroff etab 2 index nseg2 getinterval def
  223.       pop 0 2 nseg2 3 sub
  224.        { /i2 exch def
  225.          /scode startc i2 getu16 def
  226.      counttomark scode 256 min exch sub 0 max { 0 } repeat
  227.      /ecode endc i2 getu16 def
  228.      /delta iddelta i2 getu16 def
  229.      idroff i2 getu16 dup 0 eq
  230.       { pop scode 1 ecode { delta add 65535 and } for
  231.       }
  232.       {    % The +2 is for the 'reserved pad'.
  233.         /gloff exch 14 nseg2 3 mul add 2 add i2 add add def
  234.         0 1 ecode scode sub
  235.          { 2 mul gloff add etab exch getu16
  236.            dup 0 ne { delta add 65535 and } if
  237.          }
  238.         for
  239.       }
  240.      ifelse
  241.        }
  242.       for
  243.     } bind
  244.   6        % Single interval lookup.
  245.     { dup 6 getu16 { 0 exch } repeat
  246.       dup 8 getu16 0 exch 1 exch 1 sub
  247.        { 2 mul 10 add 2 copy getu16 exch pop exch }
  248.       repeat pop
  249.     } bind
  250. .dicttomark readonly def        % cmapformats
  251. /cmaparray        % <cmaptab> cmaparray -mark- <glyphs> ...
  252.  { mark exch dup 0 getu16 cmapformats exch .knownget
  253.     { exec }
  254.     { (Can't handle format ) print 0 getu16 = flush
  255.       0 1 255 { } for
  256.     }
  257.    ifelse
  258.  } bind def
  259. /postformats mark
  260.         % Each procedure in this dictionary is called as follows:
  261.         %    posttable <<proc>> glyphencoding
  262.   16#00020000    % Detailed map, required by Microsoft fonts.
  263.     { /postglyphs exch def
  264.       postglyphs 32 getu16 /numglyphs exch def
  265.       /glyphnames numglyphs 2 mul 34 add def
  266.       [ 0 1 numglyphs 1 sub
  267.        { 2 mul 34 add postglyphs exch getu16
  268.      dup 258 lt
  269.       { MacGlyphEncoding exch get
  270.       }
  271.       { 258 sub glyphnames exch
  272.          { postglyphs 1 index get 1 add add }
  273.         repeat
  274.         1 add postglyphs exch 2 copy 1 sub get getinterval cvn
  275.       }
  276.      ifelse
  277.        }
  278.       for ]
  279.     } bind
  280. .dicttomark readonly def        % postformats
  281. .dicttomark readonly def        % .loadttfontdict
  282. /.loadttfonttables    % <file> .loadttfonttables -
  283.             % Pushes .loadttfontdict & scratch dict on d-stack,
  284.             % defines f, offsets, tables
  285.  { .loadttfontdict begin
  286.    40 dict begin
  287.    /f exch def
  288.    /offsets f 12 string readstring pop def
  289.    /tables f offsets 4 getu16 16 mul string readstring pop def
  290.  } bind def
  291. /.makesfnts        % - .makesfnts -
  292.             % Defines head, sfnts
  293.  {        % Find the end of the last table, and also the end of
  294.         % the last table below the 64K mark.
  295.    0 8 16 tables length
  296.     {        % Stack: end toffset
  297.       DEBUG
  298.        { tables 1 index 8 sub 4 getinterval print ( ) print
  299.      tables 1 index getu32 =only ( ) print
  300.      tables 1 index 4 add getu32 =
  301.        }
  302.       if
  303.       tables 1 index getu32 exch tables exch 4 add getu32 add max
  304.     }
  305.    for
  306.         % Divide into 2+n strings: before glyf, glyfs, after glyf
  307.    (glyf) findtableentry pop
  308.    dup 8 getu32 /len0 exch def
  309.    12 getu32 /len1 exch def
  310.    len0 len1 add sub /len2 exch def
  311.    /sfnts [
  312.    len0 string
  313.      dup 0 offsets putinterval
  314.      dup offsets length tables putinterval
  315.      dup offsets length tables length add
  316.        len0 1 index sub getinterval
  317.        f exch dup length 0 ne { readstring } if pop pop
  318.    len1 dup maxstring gt
  319.     {        % Bad news: we'll have to split the glyfs.
  320.         % Right now we only provide for splitting into 2 parts,
  321.         % but we could generalize this without too much trouble.
  322.       f maxstring string readstring pop
  323.       exch maxstring sub
  324.     }
  325.    if string f exch readstring pop
  326.    len2 0 ne { f len2 string readstring pop } if
  327.    ] def
  328.    /head (head) findtable pop def
  329.    len1 maxstring gt
  330.     {        % Determine where to split the glyfs by scanning loca.
  331.         % The very last entry in loca may be bogus.
  332.         % What a nuisance!
  333.       (loca) findtable pop dup length
  334.       head 50 getu16 0 ne
  335.        {    % 32-bit loca
  336.      8 sub -4 0
  337.       { 1 index exch getu32 dup maxstring le { exch pop exit } if pop }
  338.        }
  339.        {    % 16-bit loca
  340.      4 sub -2 0
  341.       { 1 index exch getu16 1 bitshift dup maxstring le { exch pop exit } if pop }
  342.        }
  343.       ifelse for
  344.         % Now the top element of the stack is the length of
  345.         % the first glyf string.
  346.       sfnts 1 get dup 0 3 index getinterval
  347.     sfnts exch 1 exch put
  348.       exch 1 index length 1 index sub getinterval
  349.     sfnts 2 get concatstrings sfnts exch 2 exch put
  350.     }
  351.    if
  352.  } bind def
  353. /.loadttfont        % <file> .loadttfont <type42font>
  354.  { .loadttfonttables
  355.    .makesfnts
  356.    /upem head 18 getu16 def
  357.    (cmap) findtable pop
  358.            % The Apple cmap format is no help in determining the encoding.
  359.         % Look for a Microsoft table.  If we can't find one,
  360.         % just use the first table, whatever it is.
  361.    dup 4 8 getinterval exch        % the default
  362.    0 1 2 index 2 getu16 1 sub
  363.     { 8 mul 4 add 1 index exch 8 getinterval
  364.       dup 0 getu16 3 eq { exch 3 -1 roll pop exit } if pop
  365.     }
  366.    for
  367.         % Stack: subentry table
  368.    /cmapsub 2 index def
  369.    exch 4 getu32 1 index length 1 index sub getinterval
  370.    /cmaptab exch def
  371.         % See if we have PostScript glyph name information.
  372.    /post (post) findtable not { null } if def
  373.    /glyphencoding post null eq
  374.     { MacGlyphEncoding }
  375.     { postformats post 0 getu32 .knownget
  376.        { post exch exec }
  377.        { MacGlyphEncoding }
  378.      ifelse
  379.     }
  380.    ifelse def
  381.    /checksum head 8 getu32 def
  382.    mark
  383.      /FontType 42
  384.      /FontMatrix matrix
  385.      /PaintType 0
  386.      /FontBBox [ 36 2 42 { head exch gets16 upem div } for ]
  387.      (name) findtable
  388.       {        % Find the names from the 'name' table.
  389.     /names exch def
  390.     /FontName names 6 findname not { checksum 16 8 string cvrs } if
  391.     /FontInfo mark
  392.       names 0 findname { /Notice exch } if
  393.       names 1 findname { /FamilyName exch } if
  394.       names 4 findname { /FullName exch } if
  395.       names 5 findname { /Version exch } if
  396.       }
  397.       {        % No name table, fabricate a FontName.
  398.     /FontName checksum 16 8 string cvrs
  399.     /FontInfo mark
  400.       }
  401.      ifelse
  402.         % Stack: /FontInfo mark key1 value1 ...
  403.      post null ne
  404.       { /ItalicAngle post 4 gets32 65536.0 div
  405.     /isFixedPitch post 12 getu32 0 ne
  406.     /UnderlinePosition post 8 gets16 upem div
  407.     /UnderlineThickness post 10 gets16 upem div
  408.       }
  409.      if
  410.      counttomark 0 ne
  411.       { .dicttomark }
  412.       { pop pop }
  413.      ifelse
  414.      /Encoding
  415.        cmaptab cmaparray
  416.         % For some reason, the Symbol and WingDing fonts start with
  417.         % 192 unmapped character codes.
  418.        counttomark 384 ge
  419.     { counttomark 256 sub /skip exch def
  420.       counttomark skip neg roll skip { pop } repeat
  421.     }
  422.        if
  423.        counttomark array astore { glyphencoding exch get } forall
  424.        counttomark 256 sub dup 0 ge
  425.     { { pop } repeat }
  426.     { neg { /.notdef } repeat }
  427.        ifelse ]
  428.         % Until we can compute the MD5 fingerprint,
  429.         % just use the precomputed checksum.
  430.      /XUID [orgXUID 42 checksum]
  431.      /CharStrings glyphencoding dup length dict
  432.        0 1 3 index length 1 sub
  433.     {    % Stack: glyphencoding dict index
  434.       2 index 1 index get 2 index 1 index known
  435.        { pop pop }
  436.        { 2 index exch 3 -1 roll put }
  437.       ifelse
  438.     }
  439.        for exch pop readonly
  440.      /sfnts sfnts
  441.    .dicttomark
  442.    end end dup /FontName get exch definefont
  443.  } bind def
  444.